package service

import (
	"errors"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"guns-go/global"
	"guns-go/model"
	"guns-go/model/request"
	"guns-go/model/response"
	"guns-go/utils"
)

func SaveSysDictType(sysDictType *model.SysDictType, tx *gorm.DB) error {
	return tx.Create(sysDictType).Error
}

func QuerySysDictTypeById(dictTypeId int) (err error, dictType *model.SysDictType) {
	var sysDictType *model.SysDictType
	err = global.GVA_DB.Where("id = ?", dictTypeId).Find(&sysDictType).Error
	return err, sysDictType
}

func UpdateSysDictType(sysDictType *model.SysDictType, tx *gorm.DB) error {
	return tx.Model(&sysDictType).Updates(sysDictType).Error
}

func DropDown(d *request.SysDictTypeParam) (err error, dictS []map[string]interface{}) {

	err, sysDictType := GetDictTypeByCode(d.Code)

	if err != nil {
		return err, nil
	}

	if sysDictType.Id == 0 {
		return errors.New("字典类型不存在"), nil
	}

	err, dictDataSlice := GetDictDataListByDictTypeId(sysDictType.Id)

	if err != nil {
		return err, nil
	}

	return err, dictDataSlice
}

func GetDictTypeByCode(code string) (err error, dict *model.SysDictType) {

	var dictType *model.SysDictType
	err = global.GVA_DB.Where("code = ?", code).Find(&dictType).Error

	if err != nil {
		return err, nil
	}
	return err, dictType
}

func Tree() (err error, sysDictTreeNode []*response.SysDictTreeNode) {

	sysDictTreeNodeSlice := make([]*response.SysDictTreeNode, 0)

	var dictTypes []model.SysDictType
	err = global.GVA_DB.Where("status <= ?", 2).Find(&dictTypes).Error

	if err != nil {
		return err, nil
	}

	if len(dictTypes) > 0 {
		for _, dictType := range dictTypes {
			sysDictTreeNode := new(response.SysDictTreeNode)

			err = utils.SimpleCopyProperties(sysDictTreeNode, dictType)

			if err != nil {
				return err, nil
			}

			sysDictTreeNode.Pid = 0
			sysDictTreeNodeSlice = append(sysDictTreeNodeSlice, sysDictTreeNode)
		}
	}

	err, dictDataSlice := GetSysDictData()

	if err != nil {
		return err, nil
	}

	if len(dictDataSlice) > 0 {

		for _, dictData := range dictDataSlice {
			sysDictTreeNode := new(response.SysDictTreeNode)
			sysDictTreeNode.Id = dictData.Id
			sysDictTreeNode.Pid = *dictData.TypeId
			sysDictTreeNode.Code = dictData.Code
			sysDictTreeNode.Name = dictData.Value

			sysDictTreeNodeSlice = append(sysDictTreeNodeSlice, sysDictTreeNode)
		}
	}

	treeNodeSlice := doTreeBuild(sysDictTreeNodeSlice)

	return err, treeNodeSlice
}

func doTreeBuild(sysDictTreeNodes []*response.SysDictTreeNode) (dictNodeS []*response.SysDictTreeNode) {

	//具体构建的过程
	buildComplete := executeBuilding(sysDictTreeNodes)

	//构建之后的处理工作
	return afterBuild(buildComplete)
}

func executeBuilding(sysDictTreeNodes []*response.SysDictTreeNode) (dictNodeS []*response.SysDictTreeNode) {

	for _, node := range sysDictTreeNodes {
		buildChildNodes(sysDictTreeNodes, node, make([]*response.SysDictTreeNode, 0))
	}

	return sysDictTreeNodes
}

func buildChildNodes(totalNodes []*response.SysDictTreeNode, node *response.SysDictTreeNode, childNodeSlice []*response.SysDictTreeNode) {

	if len(totalNodes) <= 0 || node == nil {
		return
	}

	nodeSubSlice := getSubChildLevelOne(totalNodes, node)

	if len(nodeSubSlice) > 0 {
		for _, t := range nodeSubSlice {
			buildChildNodes(totalNodes, t, make([]*response.SysDictTreeNode, 0))
		}
	}

	childNodeSlice = append(childNodeSlice, nodeSubSlice...)
	node.Children = childNodeSlice
}

func getSubChildLevelOne(slice []*response.SysDictTreeNode, node *response.SysDictTreeNode) (nodeS []*response.SysDictTreeNode) {

	nodeSlice := make([]*response.SysDictTreeNode, 0)

	if len(slice) > 0 {
		for _, t := range slice {
			if t.Pid == node.Id {
				nodeSlice = append(nodeSlice, t)
			}
		}
	}
	return nodeSlice
}

func afterBuild(nodes []*response.SysDictTreeNode) (results []*response.SysDictTreeNode) {

	//去掉所有的二级节点
	resultSlice := make([]*response.SysDictTreeNode, 0)

	for _, node := range nodes {
		if node.Pid == 0 {
			resultSlice = append(resultSlice, node)
		}
	}

	return resultSlice
}

func SysDictTypePage(sysDictTypeParam *request.SysDictTypeParam, c *gin.Context) (err error, result *response.PageResult) {

	var sysDictTypeSlice []*model.SysDictType
	db := global.GVA_DB

	if sysDictTypeParam != nil {

		//根据字典类型名称模糊查询
		if sysDictTypeParam.Name != "" {
			db = db.Where("name like ?", "%"+sysDictTypeParam.Name+"%")
		}

		//根据字典类型编码模糊查询
		if sysDictTypeParam.Code != "" {
			db = db.Where("code like ?", "%"+sysDictTypeParam.Code+"%")
		}
	}
	//查询未删除的
	db = db.Where("status <> ?", 2)
	//根据排序升序排列，序号越小越在前
	db = db.Order("sort asc")

	var totalCount int64

	err = db.Find(&sysDictTypeSlice).Count(&totalCount).Error

	if err != nil {
		return err, nil
	}

	pageNo, pageSize, db := utils.DefaultPage(c, db)

	err = db.Find(&sysDictTypeSlice).Error

	if err != nil {
		return err, nil
	}

	return err, utils.CoverToPageResult(pageNo, pageSize, totalCount, sysDictTypeSlice)
}

func SysDictTypeAdd(sysDictTypeParam *request.SysDictTypeParam) error {

	//校验参数，检查是否存在重复的编码或者名称，不排除当前添加的这条记录
	err := checkParamByDictType(sysDictTypeParam, false)

	if err != nil {
		return err
	}

	//2.构造实体
	sysDictType := new(model.SysDictType)

	err = utils.SimpleCopyProperties(sysDictType, sysDictTypeParam)

	if err != nil {
		return err
	}

	var zero int8
	zero = 0

	//设置状态为启用
	sysDictType.Status = &zero

	tx := global.GVA_DB.Begin()

	//3.保存到库中
	err = SaveSysDictType(sysDictType, tx)

	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func SysDictTypeEdit(sysDictTypeParam *request.SysDictTypeParam) error {

	//1.根据id查询实体
	err, sysDictType := QuerySysDictTypeById(sysDictTypeParam.Id)

	if err != nil {
		return err
	}

	if sysDictType.Id == 0 {
		return errors.New("字典类型不存在")
	}

	//2.校验参数，是否有重复的名称和编码，排除本条记录
	err = checkParamByDictType(sysDictTypeParam, true)

	if err != nil {
		return err
	}

	err = utils.SimpleCopyProperties(sysDictType, sysDictTypeParam)

	if err != nil {
		return err
	}

	//不能修改状态，用修改状态接口修改状态
	sysDictType.Status = nil

	tx := global.GVA_DB.Begin()

	//3.更新记录
	err = UpdateSysDictType(sysDictType, tx)

	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

func SysDictTypeDelete(sysDictTypeParam *request.SysDictTypeParam) error {

	//1.根据id获取常量信息
	err, sysDictType := QuerySysDictTypeById(sysDictTypeParam.Id)

	if err != nil {
		return err
	}

	if sysDictType.Id == 0 {
		return errors.New("字典类型不存在")
	}

	var two int8
	two = 2
	//2.设置状态为已删除
	sysDictType.Status = &two

	tx := global.GVA_DB.Begin()

	err = UpdateSysDictType(sysDictType, tx)

	if err != nil {
		tx.Rollback()
		return err
	}

	//3.级联删除字典值
	err = deleteByTypeId(sysDictType.Id, 2, tx)

	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

//校验参数，是否有重复的名称和编码
func checkParamByDictType(sysDictTypeParam *request.SysDictTypeParam, isExcludeSelf bool) error {

	id := sysDictTypeParam.Id
	name := sysDictTypeParam.Name
	code := sysDictTypeParam.Code

	var sysDictTypeSlice []*model.SysDictType

	db := global.GVA_DB
	// 查询名称有无重复
	dbName := db.Where("name = ?", name).Where("status <> ?", 2)
	// 查询编码有无重复
	dbCode := db.Where("code = ?", code).Where("status <> ?", 2)

	//如果排除自己，则增加查询条件主键id不等于本条id
	if isExcludeSelf {
		dbName = dbName.Where("id <> ?", id)
		dbCode = dbCode.Where("id <> ?", id)
	}

	var countByName int64
	err := dbName.Find(&sysDictTypeSlice).Count(&countByName).Error

	if err != nil {
		return err
	}

	var countByCode int64
	err = dbCode.Find(&sysDictTypeSlice).Count(&countByCode).Error

	if err != nil {
		return err
	}

	//如果存在重复的记录，抛出异常，直接返回前端
	if countByName >= 1 {
		return errors.New("字典类型名称重复，请检查name参数")
	}

	if countByCode >= 1 {
		return errors.New("字典类型编码重复，请检查code参数")
	}

	return nil
}
